package com.candy.biz.manager;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.candy.biz.domain.entity.SysConfig;
import com.candy.biz.domain.param.SysConfigSaveParam;
import com.candy.biz.domain.vo.SysConfigVO;
import com.candy.biz.enums.ConfigTypeEnum;
import com.candy.biz.mapper.SysConfigMapper;
import com.candy.common.domain.PageVO;
import com.candy.common.enums.RedisKeyEnum;
import com.candy.common.manager.RedisManager;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.candy.biz.domain.entity.table.SysConfigTableDef.SYS_CONFIG;

/**
 * 参数配置-通用处理层。
 *
 * @author rong xi
 * @date 2023/09/18 09:18
 * @version 1.0.0
 */
@Component
@AllArgsConstructor
@Slf4j
public class SysConfigManager {

    private static SysConfigManager manager;
    private final SysConfigMapper sysConfigMapper;

    @PostConstruct
    private void init(){
        manager = this;
    }


    /**
     * 参数配置po对象转参数配置vo对象
     * @param po po对象
     * @return vo对象
     */
    public static SysConfigVO poToVo(SysConfig po){
        return CommonManager.convert(po, SysConfigVO.class);
    }

    /**
     * 参数配置分页对象转换分页视图数据
     * @param page 分页结果
     * @return 分页数据
     */
    public static PageVO<SysConfigVO> pageToPageVO(Page<SysConfig> page) {
        //转换处理
        return PageVO.of(posToVos(page.getRecords()),page.getTotalRow());
    }

    /**
     * 参数配置po集合转参数配置vo集合
     * @param pos po集合对象
     * @return vos vo集合对象
     */
    public static List<SysConfigVO> posToVos(List<SysConfig> pos){
        return CommonManager.convert(pos, SysConfigVO.class);
    }

    /**
     * 新增参数配置准备
     * @param param 新增参数
     * @return po对象
     */
    public static SysConfig insertPrepare(SysConfigSaveParam param){
        SysConfig sysConfig = BeanUtil.copyProperties(param, SysConfig.class);
        sysConfig.setId(IdUtil.getSnowflakeNextId());
        sysConfig.setCreateUser(StpUtil.getLoginIdAsLong());
        sysConfig.setCreateTime(LocalDateTime.now());
        return sysConfig;
    }

    /**
     * 修改参数配置准备
     * @param param 修改参数
     * @return po对象
     */
    public static SysConfig updatePrepare(SysConfigSaveParam param){
        SysConfig sysConfig = BeanUtil.copyProperties(param, SysConfig.class);
        sysConfig.setUpdateUser(StpUtil.getLoginIdAsLong());
        sysConfig.setUpdateTime(LocalDateTime.now());
        return sysConfig;
    }

    /**
     * 获取系统配置
     *
     * @return 系统配置map
     */
    public static Optional<Map<String,String>> getConfigMapOpt(ConfigTypeEnum configTypeEnum){
        return RedisManager.<String>getMapOpt(RedisKeyEnum.CONFIG.getKey())
                .filter(CollectionUtil::isNotEmpty)
                //从数据库读取
                .or(()->Optional.of(manager.sysConfigMapper.selectListByCondition(SYS_CONFIG.TYPE.eq(configTypeEnum.getValue()))
                                .stream().collect(Collectors.toMap(SysConfig::getConfigKey, SysConfig::getConfigValue)))
                        .filter(CollectionUtil::isNotEmpty)
                        .map(m->{
                            //缓存到redis
                            RedisManager.setMap(RedisKeyEnum.CONFIG.getKey(),m);
                            RedisManager.expire(RedisKeyEnum.CONFIG.getKey(),RedisKeyEnum.CONFIG.getTimeout());
                            return m;
                        })
                );
    }

    /**
     * 获取系统配置值
     *
     * @return 系统配置map
     */
    public static Optional<String> getConfigValueOpt(String configKey){
        return RedisManager.<String>getMapValueOpt(RedisKeyEnum.CONFIG.getKey(),configKey)
                //从数据库读取
                .or(()->Optional.ofNullable(manager.sysConfigMapper.selectOneByCondition(SYS_CONFIG.CONFIG_KEY.eq(configKey)))
                        .map(m->{
                            //缓存到redis
                            RedisManager.setMapValue(RedisKeyEnum.CONFIG.getKey(),configKey,m.getConfigValue());
                            RedisManager.expire(RedisKeyEnum.CONFIG.getKey(),RedisKeyEnum.CONFIG.getTimeout());
                            return m.getConfigValue();
                        })
                );
    }


}
